using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Web.Security;
using WWB.SitePointPrivateMessages.Core.Infrastructure.Logging;
using WWB.SitePointPrivateMessages.Core.Model.DataImport;

namespace WWB.SitePointPrivateMessages.Core.Model.Messages
{
    public class PrivateMessage : IComparable<PrivateMessage>, IEquatable<PrivateMessage>
    {
        public PrivateMessage()
        {
            ToUsers = new List<ForumUser>();
        }
        public Folder Folder { get; set; }
        public DateTime DateStamp { get; set;}
        public string Title { get; set;}
        public ForumUser FromUser { get; set;}
        public IList<ForumUser> ToUsers { get; set;}
        public string Body { get; set;}

        public string FingerPrint 
        {
            get
            {
                string fp = DateStamp.ToUniversalTime() + Title + FromUser + string.Join("", ToUsers.Select(x => x.ToString())) + Body;
                return FormsAuthentication.HashPasswordForStoringInConfigFile(fp, "md5");
            }
        }

        public int CompareTo(PrivateMessage other)
        {
            if (other == null)
            {
                throw new ArgumentNullException("other");
            }
            return DateStamp.CompareTo(other.DateStamp);
        }

        public bool Equals(PrivateMessage other)
        {
            if (other == null)
            {
                return false;
            }
            return FingerPrint == other.FingerPrint;
        }

        public override bool Equals(object obj)
        {
            var that = obj as PrivateMessage;
            return Equals(that);
        }

        public static bool operator == (PrivateMessage a, PrivateMessage b)
        {
            if (ReferenceEquals(a, b))
            {
                return true;
            }
            if (((object)a == null) || ((object)b == null))
            {
                return false;
            }
            return a.Equals(b);
        }

        public static bool operator != (PrivateMessage a, PrivateMessage b)
        {
            return !(a == b);
        }

        public override int GetHashCode()
        {
            return FingerPrint.GetHashCode();
        }

        public ExportedMessage ConvertToExport(ILogger outputLog)
        {
            outputLog.LogMessage("Converting message ID {0}", FingerPrint);
            var em = new ExportedMessage()
                         {
                             DateStamp = this.DateStamp.ToString(ExportedMessage.DateStampFormat),
                             Title = this.Title,
                             FromUser = this.FromUser.Name,
                             FromUserId = this.FromUser.Id,
                             ToUser = getToUserNames(),
                             MessageBody = Body
                         };
            return em;
        }

        public string ToUserNames
        {
            get { return getToUserNames(); }
        }

        private string getToUserNames()
        {
            if (ToUsers == null)
            {
                return string.Empty;
            }
            return string.Join(", ", ToUsers.Select(x => x.Name));
        }

        public bool IsRelatedToUsers(IEnumerable<int> selectedUsers)
        {
            if (selectedUsers.Contains(FromUser.Id))
            {
                return true;
            }
            if (ToUsers.Any(touser => selectedUsers.Contains(touser.Id)))
            {
                return true;
            }
            return false;
        }

        public string HtmlBody()
        {
            return Body.Replace("\n", "<br />");
        }
    }
}